use eframe::egui;
use egui::ViewportBuilder;

fn main() -> Result<(), eframe::Error> {
    let options = eframe::NativeOptions {
        viewport: ViewportBuilder::default().with_inner_size([320.0, 480.0]),
        ..Default::default()
    };

    eframe::run_native(
        "科学计算器",
        options,
        Box::new(|cc| {
            // 配置字体
            let mut fonts = egui::FontDefinitions::default();

            // 添加中文字体支持
            fonts.font_data.insert(
                "microsoft_yahei".to_owned(),
                egui::FontData::from_static(include_bytes!(
                    "../assets/SourceHanSansCN-Regular.otf"
                )),
            );

            // 将中文字体设置为首选字体
            fonts
                .families
                .get_mut(&egui::FontFamily::Proportional)
                .unwrap()
                .insert(0, "microsoft_yahei".to_owned());

            cc.egui_ctx.set_fonts(fonts);

            Box::new(CalculatorApp::default())
        }),
    )
}

struct CalculatorApp {
    expression: String, // 用于存储完整算式
    result: f64,
    is_radian: bool,       // 添加角度/弧度模式标志
    base_mode: NumberBase, // 添加进制模式
}

// 添加进制枚举
#[derive(Clone, Copy, PartialEq)]
enum NumberBase {
    Decimal,
    Binary,
    Octal,
    Hexadecimal,
}

impl Default for CalculatorApp {
    fn default() -> Self {
        Self {
            expression: String::new(),
            result: 0.0,
            is_radian: false,
            base_mode: NumberBase::Decimal, // 默认十进制
        }
    }
}

impl eframe::App for CalculatorApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            ui.vertical(|ui| {
                // 使用格式化的表达式显示
                ui.label(format!("算式: {}", self.format_expression()));
                ui.label(format!("结果: {}", self.format_result()));

                // 数字按钮
                self.render_number_buttons(ui);

                // 添加数学常数按钮
                ui.horizontal(|ui| {
                    if ui.button("π").clicked() {
                        self.append_constant(std::f64::consts::PI);
                    }
                    if ui.button("e").clicked() {
                        self.append_constant(std::f64::consts::E);
                    }
                });

                // 基本运算
                ui.horizontal(|ui| {
                    if ui.button("+").clicked() {
                        self.append_operator('+');
                    }
                    if ui.button("-").clicked() {
                        self.append_operator('-');
                    }
                    if ui.button("×").clicked() {
                        self.append_operator('*');
                    }
                    if ui.button("÷").clicked() {
                        self.append_operator('/');
                    }
                });

                // 科学运算
                ui.horizontal(|ui| {
                    if ui.button("sin").clicked() {
                        self.append_function("sin(");
                    }
                    if ui.button("cos").clicked() {
                        self.append_function("cos(");
                    }
                    if ui.button("tan").clicked() {
                        self.append_function("tan(");
                    }
                    if ui.button("√").clicked() {
                        self.append_function("sqrt(");
                    }
                });

                // 添加幂运算和对数运算按钮
                ui.horizontal(|ui| {
                    if ui.button("^").clicked() {
                        self.append_operator('^');
                    }
                    if ui.button("ln").clicked() {
                        self.append_function("ln(");
                    }
                    if ui.button("log").clicked() {
                        self.append_function("log(");
                    }
                });
                // 添加括号按钮
                ui.horizontal(|ui| {
                    if ui.button("(").clicked() {
                        self.append_operator('(');
                    }
                    if ui.button(")").clicked() {
                        self.append_operator(')');
                    }
                });

                // 添加角度/弧度切换按钮
                ui.horizontal(|ui| {
                    ui.label("模式：");
                    if ui.radio_value(&mut self.is_radian, false, "角度").clicked() {
                        // 切换到角度模式时不需要特殊处理
                    }
                    if ui.radio_value(&mut self.is_radian, true, "弧度").clicked() {
                        // 切换到弧度模式时不需要特殊处理
                    }
                });

                // 添加进制选择按钮
                ui.horizontal(|ui| {
                    ui.label("进制：");
                    let old_base = self.base_mode;
                    if ui
                        .radio_value(&mut self.base_mode, NumberBase::Decimal, "十进制")
                        .clicked()
                    {
                        self.convert_all_numbers(old_base, NumberBase::Decimal);
                    }
                    if ui
                        .radio_value(&mut self.base_mode, NumberBase::Binary, "二进制")
                        .clicked()
                    {
                        self.convert_all_numbers(old_base, NumberBase::Binary);
                    }
                    if ui
                        .radio_value(&mut self.base_mode, NumberBase::Octal, "八进制")
                        .clicked()
                    {
                        self.convert_all_numbers(old_base, NumberBase::Octal);
                    }
                    if ui
                        .radio_value(&mut self.base_mode, NumberBase::Hexadecimal, "十六进制")
                        .clicked()
                    {
                        self.convert_all_numbers(old_base, NumberBase::Hexadecimal);
                    }
                });

                // 等于和清除按钮
                ui.horizontal(|ui| {
                    if ui.button("=").clicked() {
                        self.calculate_expression();
                    }
                    if ui.button("C").clicked() {
                        self.expression.clear();
                        self.result = 0.0;
                    }
                    if ui.button("←").clicked() {
                        self.backspace();
                    }
                });
            });
        });
    }
}

impl CalculatorApp {
    /// 计算表达式的方法
    fn calculate_expression(&mut self) {
        // 移除所有空格
        let expr = self.expression.replace(" ", "");
        let mut nums: Vec<f64> = Vec::new();
        let mut ops: Vec<String> = Vec::new();
        let mut current_num = String::new();
        let mut i = 0;

        while i < expr.len() {
            let c = expr.chars().nth(i).unwrap();
            match c {
                '0'..='9' | 'A'..='F' | '.' => {
                    current_num.push(c);
                    i += 1;
                }
                '(' => {
                    if !current_num.is_empty() {
                        if let Some(num) = self.parse_number(&current_num, self.base_mode) {
                            nums.push(num);
                            ops.push("*".to_string());
                        }
                        current_num.clear();
                    }
                    ops.push("(".to_string());
                    i += 1;
                }
                ')' => {
                    if !current_num.is_empty() {
                        if let Some(num) = self.parse_number(&current_num, self.base_mode) {
                            nums.push(num);
                        }
                        current_num.clear();
                    }
                    while !ops.is_empty() && ops.last().unwrap() != "(" {
                        self.apply_operation(&mut nums, ops.pop().unwrap());
                    }
                    ops.pop(); // 弹出左括号

                    // 检查是否是函数调用
                    if !ops.is_empty() {
                        let last_op = ops.last().unwrap();
                        if ["sin", "cos", "tan", "sqrt", "ln", "log"].contains(&last_op.as_str()) {
                            let func = ops.pop().unwrap();
                            if let Some(last_num) = nums.last_mut() {
                                // 如果是角度模式，先将角度转换为弧度
                                let angle = if !self.is_radian {
                                    *last_num * std::f64::consts::PI / 180.0
                                } else {
                                    *last_num
                                };

                                *last_num = match func.as_str() {
                                    "sin" => angle.sin(),
                                    "cos" => angle.cos(),
                                    "tan" => angle.tan(),
                                    "sqrt" => angle.sqrt(),
                                    "ln" => angle.ln(),
                                    "log" => angle.log10(),
                                    _ => *last_num,
                                };
                            }
                        }
                    }
                    i += 1;
                }
                '+' | '-' | '*' | '/' | '^' => {
                    if !current_num.is_empty() {
                        if let Some(num) = self.parse_number(&current_num, self.base_mode) {
                            nums.push(num);
                        }
                        current_num.clear();
                    }

                    let curr_op = c.to_string();
                    while !ops.is_empty()
                        && ops.last().unwrap() != "("
                        && self.should_calculate_first(ops.last().unwrap(), &curr_op)
                    {
                        self.apply_operation(&mut nums, ops.pop().unwrap());
                    }
                    ops.push(curr_op);
                    i += 1;
                }
                's' => {
                    if expr[i..].starts_with("sin") {
                        ops.push("sin".to_string());
                        i += 3;
                    } else if expr[i..].starts_with("sqrt") {
                        ops.push("sqrt".to_string());
                        i += 4;
                    } else {
                        i += 1;
                    }
                }
                'c' => {
                    if expr[i..].starts_with("cos") {
                        ops.push("cos".to_string());
                        i += 3;
                    } else {
                        i += 1;
                    }
                }
                't' => {
                    if expr[i..].starts_with("tan") {
                        ops.push("tan".to_string());
                        i += 3;
                    } else {
                        i += 1;
                    }
                }
                'l' => {
                    if expr[i..].starts_with("ln") {
                        ops.push("ln".to_string());
                        i += 2;
                    } else if expr[i..].starts_with("log") {
                        ops.push("log".to_string());
                        i += 3;
                    } else {
                        i += 1;
                    }
                }
                _ => i += 1,
            }
        }

        // 处理最后一个数字
        if !current_num.is_empty() {
            if let Some(num) = self.parse_number(&current_num, self.base_mode) {
                nums.push(num);
            }
        }

        // 处理剩余的运算符
        while !ops.is_empty() {
            let op = ops.pop().unwrap();
            if op != "(" {
                self.apply_operation(&mut nums, op);
            }
        }

        // 设置结果
        if !nums.is_empty() {
            self.result = nums[0];
        }
    }

    /// 应用运算符
    fn apply_operation(&mut self, nums: &mut Vec<f64>, op: String) {
        match op.as_str() {
            "+" | "-" | "*" | "/" => {
                if nums.len() < 2 {
                    return;
                }
                let b = nums.pop().unwrap();
                let a = nums.pop().unwrap();
                let result = match op.as_str() {
                    "+" => a + b,
                    "-" => a - b,
                    "*" => a * b,
                    "/" => a / b,
                    _ => 0.0,
                };
                nums.push(result);
            }
            "^" => {
                if nums.len() < 2 {
                    return;
                }
                let b = nums.pop().unwrap();
                let a = nums.pop().unwrap();
                nums.push(a.powf(b));
            }
            "sin" | "cos" | "tan" | "sqrt" => {
                if let Some(last_num) = nums.last_mut() {
                    *last_num = match op.as_str() {
                        "sin" => last_num.sin(),
                        "cos" => last_num.cos(),
                        "tan" => last_num.tan(),
                        "sqrt" => last_num.sqrt(),
                        _ => *last_num,
                    };
                }
            }
            "ln" => {
                if let Some(last_num) = nums.last_mut() {
                    *last_num = last_num.ln();
                }
            }
            "log" => {
                if let Some(last_num) = nums.last_mut() {
                    *last_num = last_num.log10();
                }
            }
            _ => {}
        }
    }

    /// 检查是否应该优先计算之前的运算符
    fn should_calculate_first(&self, prev_op: &str, curr_op: &str) -> bool {
        let precedence = |op: &str| -> u8 {
            match op {
                "+" | "-" => 1,
                "*" | "/" => 2,
                "^" => 3,
                "(" => 0,
                "sin" | "cos" | "tan" | "sqrt" | "ln" | "log" => 4,
                _ => 0,
            }
        };

        let prev_precedence = precedence(prev_op);
        let curr_precedence = precedence(curr_op);

        // 幂运算是右结合的，所以当优先级相同时不应该立即计算
        if prev_op == "^" && curr_op == "^" {
            return false;
        }

        prev_precedence >= curr_precedence
    }

    /// 添加数字到表达式中
    fn append_digit(&mut self, digit: char) {
        if self.is_valid_digit_for_base(digit) {
            self.expression.push(digit);
        }
    }

    /// 添加运算符到表达式中
    fn append_operator(&mut self, op: char) {
        self.expression.push(op);
    }

    /// 添加常数到表达式中
    fn append_constant(&mut self, value: f64) {
        let formatted = self.format_number_base(value, self.base_mode);
        self.expression.push_str(&formatted);
    }

    /// 添加函数到表达式中
    fn append_function(&mut self, func: &str) {
        self.expression.push_str(func);
    }

    /// 退格功能
    fn backspace(&mut self) {
        if self.expression.ends_with("sin(") {
            self.expression.truncate(self.expression.len() - 4);
        } else if self.expression.ends_with("cos(") || self.expression.ends_with("tan(") {
            self.expression.truncate(self.expression.len() - 4);
        } else if self.expression.ends_with("sqrt(") {
            self.expression.truncate(self.expression.len() - 5);
        } else if self.expression.ends_with("ln(") {
            self.expression.truncate(self.expression.len() - 3);
        } else if self.expression.ends_with("log(") {
            self.expression.truncate(self.expression.len() - 4);
        } else {
            self.expression.pop();
        }
    }

    /// 检查输入的数字是否符合当前进制
    fn is_valid_digit_for_base(&self, digit: char) -> bool {
        match self.base_mode {
            NumberBase::Binary => digit == '0' || digit == '1' || digit == '.',
            NumberBase::Octal => digit.is_digit(8) || digit == '.',
            NumberBase::Decimal => digit.is_digit(10) || digit == '.',
            NumberBase::Hexadecimal => digit.is_ascii_hexdigit() || digit == '.',
        }
    }

    /// 将 f64 数字格式化为指定进制的字符串
    fn format_number_base(&self, num: f64, base: NumberBase) -> String {
        let int_part = num.trunc() as i64;
        let frac_part = num.fract();

        let int_str = match base {
            NumberBase::Decimal => format!("{}", int_part),
            NumberBase::Binary => format!("{:b}", int_part),
            NumberBase::Octal => format!("{:o}", int_part),
            NumberBase::Hexadecimal => format!("{:X}", int_part),
        };

        if frac_part != 0.0 {
            format!(
                "{}.{}",
                int_str,
                format!("{:.6}", frac_part)
                    .trim_start_matches("0.")
                    .trim_end_matches('0')
            )
        } else {
            int_str
        }
    }

    /// 解析表达式中的一个数字字符串为 f64
    fn parse_number(&self, num_str: &str, base: NumberBase) -> Option<f64> {
        match base {
            NumberBase::Decimal => num_str.parse::<f64>().ok(),
            NumberBase::Binary => {
                let parts: Vec<&str> = num_str.split('.').collect();
                let int_part = i64::from_str_radix(&parts[0], 2).ok()? as f64;
                let frac_part = if parts.len() > 1 {
                    let mut frac = 0.0;
                    for (i, c) in parts[1].chars().enumerate() {
                        let digit = if c.is_digit(2) {
                            (c as u8 - b'0') as f64
                        } else {
                            return None;
                        };
                        frac += digit / 2_f64.powi((i + 1) as i32);
                    }
                    frac
                } else {
                    0.0
                };
                Some(int_part + frac_part)
            }
            NumberBase::Octal => {
                let parts: Vec<&str> = num_str.split('.').collect();
                let int_part = i64::from_str_radix(&parts[0], 8).ok()? as f64;
                let frac_part = if parts.len() > 1 {
                    let mut frac = 0.0;
                    for (i, c) in parts[1].chars().enumerate() {
                        let digit = if c.is_digit(8) {
                            (c as u8 - b'0') as f64
                        } else {
                            return None;
                        };
                        frac += digit / 8_f64.powi((i + 1) as i32);
                    }
                    frac
                } else {
                    0.0
                };
                Some(int_part + frac_part)
            }
            NumberBase::Hexadecimal => {
                let parts: Vec<&str> = num_str.split('.').collect();
                let int_part = i64::from_str_radix(&parts[0], 16).ok()? as f64;
                let frac_part = if parts.len() > 1 {
                    let mut frac = 0.0;
                    for (i, c) in parts[1].chars().enumerate() {
                        let digit = match c.to_ascii_uppercase() {
                            '0'..='9' => (c as u8 - b'0') as f64,
                            'A'..='F' => ((c as u8 - b'A') + 10) as f64,
                            _ => return None,
                        };
                        frac += digit / 16_f64.powi((i + 1) as i32);
                    }
                    frac
                } else {
                    0.0
                };
                Some(int_part + frac_part)
            }
        }
    }

    /// 转换所有数字的方法，只转换数字，保留运算符和函数
    fn convert_all_numbers(&mut self, old_base: NumberBase, new_base: NumberBase) {
        let mut new_expression = String::new();
        let mut num_buffer = String::new();
        let functions = ["sin", "cos", "tan", "sqrt", "ln", "log"];
        let mut i = 0;
        let expr = &self.expression;

        while i < expr.len() {
            // 检查是否有函数匹配
            let mut matched_function = None;
            for func in &functions {
                if expr[i..].starts_with(func) {
                    matched_function = Some(*func);
                    break;
                }
            }

            if let Some(func) = matched_function {
                // 如果前面有数字积累，则先处理数字
                if !num_buffer.is_empty() {
                    if let Some(num) = self.parse_number(&num_buffer, old_base) {
                        new_expression.push_str(&self.format_number_base(num, new_base));
                    } else {
                        new_expression.push_str(&self.format_number_base(0.0, new_base));
                        // 默认0
                    }
                    num_buffer.clear();
                }
                // 添加函数名
                new_expression.push_str(func);
                i += func.len();
                continue;
            }

            let c = expr.chars().nth(i).unwrap();
            if c.is_ascii_hexdigit() || c == '.' {
                num_buffer.push(c);
            } else if c == 'π' || c == 'e' {
                new_expression.push(c);
            } else {
                if !num_buffer.is_empty() {
                    if let Some(num) = self.parse_number(&num_buffer, old_base) {
                        new_expression.push_str(&self.format_number_base(num, new_base));
                    } else {
                        new_expression.push_str(&self.format_number_base(0.0, new_base));
                        // 默认0
                    }
                    num_buffer.clear();
                }
                new_expression.push(c);
            }
            i += 1;
        }

        // 处理最后的数字
        if !num_buffer.is_empty() {
            if let Some(num) = self.parse_number(&num_buffer, old_base) {
                new_expression.push_str(&self.format_number_base(num, new_base));
            } else {
                new_expression.push_str(&self.format_number_base(0.0, new_base));
                // 默认0
            }
        }

        self.expression = new_expression;

        // 保持 result 不变（f64）
        self.result = match new_base {
            NumberBase::Decimal => self.result,
            _ => self.result,
        };

        self.base_mode = new_base;
    }

    /// 格式化数字，每4位添加一个空格，从低位开始
    fn format_number(&self, num_str: &str) -> String {
        let parts: Vec<&str> = num_str.split('.').collect();
        let mut result = String::new();

        // 处理整数部分
        let integer_part = parts[0];
        let mut formatted_integer = String::new();
        let mut count = 0;

        // 从右向左每4位添加空格
        for c in integer_part.chars().rev() {
            if count > 0 && count % 4 == 0 {
                formatted_integer.push(' ');
            }
            formatted_integer.push(c);
            count += 1;
        }

        // 反转回正常顺序
        result.extend(formatted_integer.chars().rev());

        // 如果有小数部分，添加小数点和小数部分
        if parts.len() > 1 {
            result.push('.');
            result.push_str(parts[1]);
        }

        result
    }

    /// 格式化结果的方法
    fn format_result(&self) -> String {
        // 将结果转换为目标进制
        let formatted_base = self.format_number_base(self.result, self.base_mode);
        // 如果转换后的结果长度超过4，应用格式化以添加空格
        if formatted_base.len() > 4 {
            self.format_number(&formatted_base)
        } else {
            formatted_base
        }
    }

    /// 格式化表达式的方法，只转换数字，保留运算符
    fn format_expression(&self) -> String {
        let mut formatted = String::new();
        let mut num_buffer = String::new();
        let functions = ["sin", "cos", "tan", "sqrt", "ln", "log"];
        let mut i = 0;
        let expr = &self.expression;

        while i < expr.len() {
            // 检查是否有函数匹配
            let mut matched_function = None;
            for func in &functions {
                if expr[i..].starts_with(func) {
                    matched_function = Some(*func);
                    break;
                }
            }

            if let Some(func) = matched_function {
                // 如果前面有数字积累，则先处理数字
                if !num_buffer.is_empty() {
                    if let Some(num) = self.parse_number(&num_buffer, self.base_mode) {
                        let formatted_num =
                            self.format_number(&self.format_number_base(num, self.base_mode));
                        formatted.push_str(&formatted_num);
                    } else {
                        formatted.push_str(&self.format_number_base(0.0, self.base_mode));
                        // 默认0
                    }
                    num_buffer.clear();
                }
                // 添加函数名
                formatted.push_str(func);
                i += func.len();
                continue;
            }

            let c = expr.chars().nth(i).unwrap();
            if c.is_ascii_hexdigit() || c == '.' {
                num_buffer.push(c);
            } else if c == 'π' || c == 'e' {
                formatted.push(c);
            } else {
                if !num_buffer.is_empty() {
                    if let Some(num) = self.parse_number(&num_buffer, self.base_mode) {
                        let formatted_num =
                            self.format_number(&self.format_number_base(num, self.base_mode));
                        formatted.push_str(&formatted_num);
                    } else {
                        formatted.push_str(&self.format_number_base(0.0, self.base_mode));
                        // 默认0
                    }
                    num_buffer.clear();
                }
                formatted.push(c);
            }
            i += 1;
        }

        // 处理最后的数字
        if !num_buffer.is_empty() {
            if let Some(num) = self.parse_number(&num_buffer, self.base_mode) {
                let formatted_num =
                    self.format_number(&self.format_number_base(num, self.base_mode));
                formatted.push_str(&formatted_num);
            } else {
                formatted.push_str(&self.format_number_base(0.0, self.base_mode));
                // 默认0
            }
        }

        formatted
    }

    /// 渲染数字按钮，根据当前进制模式显示不同的按钮
    fn render_number_buttons(&mut self, ui: &mut egui::Ui) {
        match self.base_mode {
            NumberBase::Binary => {
                ui.horizontal(|ui| {
                    for &digit in &['.', '0', '1'] {
                        if ui.button(digit.to_string()).clicked() {
                            self.append_digit(digit);
                        }
                    }
                });
            }
            NumberBase::Octal => {
                for row in &[['5', '6', '7'], ['2', '3', '4'], ['.', '0', '1']] {
                    ui.horizontal(|ui| {
                        for &digit in row {
                            if ui.button(digit.to_string()).clicked() {
                                self.append_digit(digit);
                            }
                        }
                    });
                }
            }
            NumberBase::Decimal => {
                ui.horizontal(|ui| {
                    for i in 7..=9 {
                        if ui.button(i.to_string()).clicked() {
                            self.append_digit(i.to_string().chars().next().unwrap());
                        }
                    }
                });

                ui.horizontal(|ui| {
                    for i in 4..=6 {
                        if ui.button(i.to_string()).clicked() {
                            self.append_digit(i.to_string().chars().next().unwrap());
                        }
                    }
                });

                ui.horizontal(|ui| {
                    for i in 1..=3 {
                        if ui.button(i.to_string()).clicked() {
                            self.append_digit(i.to_string().chars().next().unwrap());
                        }
                    }
                });

                ui.horizontal(|ui| {
                    if ui.button("0").clicked() {
                        self.append_digit('0');
                    }
                    if ui.button(".").clicked() {
                        self.append_digit('.');
                    }
                });
            }
            NumberBase::Hexadecimal => {
                ui.horizontal(|ui| {
                    for &digit in &['A', 'B', 'C', 'D', 'E', 'F'] {
                        if ui.button(digit.to_string()).clicked() {
                            self.append_digit(digit);
                        }
                    }
                });
                ui.horizontal(|ui| {
                    for &digit in &['6', '7', '8', '9'] {
                        if ui.button(digit.to_string()).clicked() {
                            self.append_digit(digit);
                        }
                    }
                });
                ui.horizontal(|ui| {
                    for &digit in &['2', '3', '4', '5'] {
                        if ui.button(digit.to_string()).clicked() {
                            self.append_digit(digit);
                        }
                    }
                });
                ui.horizontal(|ui| {
                    for &digit in &['.', '0', '1'] {
                        if ui.button(digit.to_string()).clicked() {
                            self.append_digit(digit);
                        }
                    }
                });
            }
        }
    }
}
